import { App, Component, createApp, h, ref } from "vue";
import { Dialog, DialogProps } from "tdesign-vue-next";
import { setupComponentsWithModal } from "./components";
import { ProFormOption, ProFormProps, ProFormRef } from "tdesign-pro-component";

interface FormModalOption<T> {
    options: ProFormOption[];
    request?: () => Promise<NullAble<T>>;
    onSubmit: (data: T) => void;
}

export default function useFormModal<T>(component: Component<ProFormProps>, formModalOption: FormModalOption<T>, dialogProps?: DialogProps, componentProps?: Optional<ProFormProps, 'request' | 'options'>) {

    const visible = ref(false);
    const proFormRef = ref<NullAble<ProFormRef>>(null);

    const dialog = () => h(Dialog,
        {
            ...dialogProps as any,
            visible: visible.value,
            onCancel: close,
            onClose: close,
            onConfirm: async () => {
                proFormRef.value?.validate().then(() => {
                    proFormRef.value?.submit();
                    setTimeout(() => {
                        close();
                    }, 200);
                });
            }
        },
        {
            default: () => h(component, { 
                ref: proFormRef, hideFooter: true, 
                ...componentProps, 
                onSubmit: formModalOption.onSubmit,
                options: formModalOption.options,
                request: formModalOption.request
            } as any)
        });

    let app: NullAble<App> = createApp(dialog);

    let div: NullAble<HTMLDivElement> = document.createElement('div');

    function open() {
        if (!app) {
            app = createApp(dialog);
        }

        if (!div) {
            div = document.createElement('div');
        }

        setupComponentsWithModal(app);

        document.body.appendChild(div);

        app.mount(div);

        visible.value = true;
    }

    function close() {
        visible.value = false;
        setTimeout(() => {
            if (app) {
                app.unmount();
            }
            if (div) {
                document.body.removeChild(div!);
            }
            app = null;
            div = null;
        }, 500)
    }

    return [open, close];
}